#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#include <libdaemon/dfork.h>
#include <libdaemon/dsignal.h>
#include <libdaemon/dlog.h>
#include <libdaemon/dpid.h>
#include <libdaemon/dexec.h>

#include "l0001-0/l0001-0.h"
#include "l0002-0/l0002-0.h"
#define MODNAME	"[DMN]"

extern daemon_pid_file_proc_t daemon_pid_file_proc;
#ifndef PATH_MAX
#define PATH_MAX 512
#endif
typedef const char* (*daemon_pid_file_proc_t)(void);
const char *daemon_pid_file_proc_run(void) {
    static char fn[PATH_MAX];
    snprintf(fn, sizeof(fn), "/tmp/%s.pid", daemon_pid_file_ident ? daemon_pid_file_ident : "unknown");

    return fn;
}

int daemonize_quit() {

    /* Do a cleanup */
    daemon_signal_done();
    daemon_pid_file_remove();
    return 0;
}

int l0031_0_daemonize(const char* pid_file_name) {
    int retval = -1;
    pid_t pid;
    daemon_pid_file_ident = daemon_log_ident = pid_file_name;
    // ERRSYS_INFOPRINT("<%s>\n", daemon_pid_file_proc());
    daemon_pid_file_proc = daemon_pid_file_proc_run;
        /* Check that the daemon is not rung twice a the same time */
    if ((pid = daemon_pid_file_is_running()) >= 0) {
        ERRSYS_FATALPRINT("Daemon already running on PID file %u\n", pid);
        return retval;
        
    }
    ERRSYS_INFOPRINT("pid file: <%s>\n", daemon_pid_file_proc());

    /* Prepare for return value passing from the initialization procedure of the daemon process */
    daemon_retval_init();
    /* Do the fork */
    if ((pid = daemon_fork()) < 0) {

        /* Exit on error */
        daemon_retval_done();
        ERRSYS_FATALPRINT("Could not fork daemon process.\n");
        return retval;
        
    } else if (pid) { /* The parent */
        int ret;

        /* Wait for 20 seconds for the return value passed from the daemon process */
        if ((ret = daemon_retval_wait(20)) < 0) {
            ERRSYS_FATALPRINT("Could not recieve return value from daemon process.\n");
            return pid;
        }
        /* parent return */
        ERRSYS_INFOPRINT("Parent process %d exit\n", (int)getpid());
        exit(0);
        
    } else { /* The daemon */
        ERRSYS_INFOPRINT("Subprocess %d\n", (int)getpid());
        /* Close FDs */
        if (daemon_close_all(-1) < 0) {
            ERRSYS_FATALPRINT("Failed to close all file descriptors: %s\n", strerror(errno));

            /* Send the error condition to the parent process */
            daemon_retval_send(1);
            goto finish;
        }

        /* Create the PID file */
        if (daemon_pid_file_create() < 0) {
            ERRSYS_FATALPRINT("Could not create PID file (%s).\n", strerror(errno));

            /* Send the error condition to the parent process */
            daemon_retval_send(1);
            goto finish;
        }
    
        /* Send OK to parent process */
        daemon_retval_send(0);
        ERRSYS_INFOPRINT("put in background.\n");
        return 0;

    }

finish:
    daemonize_quit();
    ERRSYS_INFOPRINT("finish quit.\n");
    return retval;
}
